import java.util.*;
import java.awt.*;
import java.awt.event.KeyEvent;

import com.speljohan.rsbot.bot.*;
import com.speljohan.rsbot.event.listeners.*;
import com.speljohan.rsbot.script.*;
import com.speljohan.rsbot.script.wrappers.*;
import com.speljohan.rsbot.util.*;

@ScriptManifest(
		authors = { "Absox" },
		category = "Magic",
		name = "MTAEnchant",
		version = .57,
		
		description = "<html>" +
		"<head><style type=\"text/css\">\n" +
		"body {\n" +
		"font-family: Arial, Helvetica, sans-serif;\n" +
		"}\n" +
		"\n" +
		"p {\n" +
		"size: 12px;\n" +
		"}\n" +
		"</style></head>\n" +
		"<body>\n" +
		"<center><h2>MageTrainingEnchanter v" + .57 + "</h2>" +
		"<p>By Absox</p></center>\n" +
		"<p>Script Description:\n" +
		"<ul>\n" +
		"<li>XP Mode: Picks up orbs and enchants them, then deposits</li>\n" +
		"<li>Pizazz Points Mode: Picks up dragonstones, enchants them, then world hops</li>\n" +
		"<li>Most cost efficient at 87+ Magic, 57+ minimum requirement</li>\n" +
		"<li>Start in Mage Training Arena, <b>inside</b> Enchantment Arena</li>\n" +
		"<li>Bring cosmics, and staff to supply all elemental runes for desired enchant-jewelry spell</li>\n" +
		"<li>For your world select screen, make sure you have <b>Members</b> worlds on top</li>\n" +
		"</ul>\n" +
		"</p><br>\n" +
		"<p>Spell: \n" +
		"<select name=\"castType\">\n" +
		"<option>Onyx</option>\n" +
		"<option>Dragonstone</option>\n" +
		"<option>Diamond</option>\n" +
		"</select><br>\n" +
		"Mode: \n" +
		"<select name=\"mode\">\n" +
		"<option>XP</option>\n" +
		"<option>Pizazz Points</option><br>\n" +
		"Antiban: <input type=\"checkbox\" name=\"antiban\" value=\"true\" checked=\"checked\" /><br>\n" +
		"Debug Logs: <input type=\"checkbox\" name=\"debug\" value=\"true\" /></p>\n" +
		"</body>\n" +
		"</html>"
		
		)

public class MageTrainingEnchanter extends Script implements PaintListener {
	
	public long startTime;
	public long antiTime;

	public int castCount;
	public int startMageLevel;
	public int startMageXp;
	public int startPoints;
	public int pointsGained;
	
	public String castType;
	public String state;
	public String status = "Starting...";
	public String mode;
	
	public boolean StartedY;
	public boolean antiban;
	public boolean debug;
	
	public int[] shapeIDs = { 10799, 10800, 10801, 10802 };
	public int dstoneID = 6903;
	public int[] shapeItemIDs = { 6898, 6899, 6900, 6901, 6903 };
	
	public RSTile[] point1 = { 
		new RSTile (3352, 9651),
		new RSTile (3376, 9651),
		new RSTile (3376, 9628),
		new RSTile (3352, 9628)
	};
	
	public RSTile[] point2 = {
		new RSTile (3357, 9647),
		new RSTile (3371, 9647),
		new RSTile (3371, 9634),
		new RSTile (3357, 9634)
	};
	
	public RSTile[] point3 = {
		new RSTile (3362, 9640),
		new RSTile (3363, 9641),
		new RSTile (3364, 9640),
		new RSTile (3363, 9639)
	};
	
	public RSTile[] dstoneSpawns = {
		new RSTile (3359, 9632),
		new RSTile (3354, 9646),
		new RSTile (3353, 9635),
		new RSTile (3375, 9633),
		new RSTile (3374, 9643),
		new RSTile (3373, 9651)
	};
	
	public boolean isWelcomeButton() {
		final RSInterface welcomeInterface = RSInterface.getInterface(378);
		if (welcomeInterface.getChild(45).getAbsoluteX() > 20
				|| !welcomeInterface.getChild(117).getText().equals(
						"10.1120.190")
				&& !welcomeInterface.getChild(117).getText().equals("")) {
			log("We still are in Welcome Screen");
			return true;
		} else {
			return false;
		}
	}
	
	public boolean onStart(Map<String, String> args) {
		castType = args.get("castType");
		
		mode = args.get("mode");
		
		if (args.get("antiban") != null) {
			antiban = true;
		}
		
		if (args.get("debug") != null) {
			debug = true;
		}
		
		return true;
	}
	
		public void onRepaint (Graphics g) {
			
		Color BG = new Color (50, 50, 50, 200);
        int x = 10;
        int y = 4;
		int mageXpGained = 0;
		
		if (startTime == 0) {
			 startTime = System.currentTimeMillis();
			 int interval = random(30000, 50000);
			 antiTime = System.currentTimeMillis() + interval;
			 
			if (debug)
			log ("Engaging antiban in " + interval / 1000 + " seconds...");
			 
		}
		
		if (startMageXp == 0) {
			startMageXp = skills.getCurrentSkillExp(Constants.STAT_MAGIC);
		}
		
		RSInterface enchantPanel = RSInterface.getInterface(195);
		if (enchantPanel.isValid()) {
			
			if (startPoints == 0) {
				startPoints = Integer.parseInt(enchantPanel.getChild(9).getText());
			}
			
			pointsGained = Integer.parseInt(enchantPanel.getChild(9).getText()) - startPoints;
		}
		
		mageXpGained = skills.getCurrentSkillExp(Constants.STAT_MAGIC) - startMageXp;
		
		long millis = System.currentTimeMillis() - startTime;
		long hours = millis / (1000 * 60 * 60);
		millis -= hours * 1000 * 60 * 60;
		long minutes = millis / (1000 * 60);
		millis -= minutes * 1000 * 60;
		long seconds = millis / 1000;
		
		if (castType.equals("Dragonstone")) {
			castCount = (int) Math.round((mageXpGained / 58.5));
		} else if (castType.equals("Onyx")) {
			castCount = (int) Math.round((mageXpGained / 72.75));
		} else {
			castCount = (int) Math.round((mageXpGained / 50.25));
		}
		
        g.setColor(BG);
        g.fill3DRect(x-6, y, 250, 150, true);
		
		g.setColor(Color.cyan);
		g.setFont(new Font("Verdana", Font.BOLD, 14));
		g.drawString("MageTrainingEnchanter v" + getClass().getAnnotation(ScriptManifest.class).version(), x, y+=15);
		g.setFont(new Font("Verdana", Font.PLAIN, 12));
		g.drawString("Casting: " + castType, x, y+=15);
		g.drawString("Status: " + status, x, y+=15);
		g.drawString("Runtime: " + hours + ":" + minutes + ":" + seconds, x, y+=15);
		g.drawString("Casts: " + castCount, x, y+=15);
		g.drawString("Magic EXP Gained: " + mageXpGained, x, y+=15);
		g.drawString("Pizazz Points Gained: " + pointsGained, x, y+=15);
		g.drawString("Mode: " + mode, x, y+=15);

		if (antiban) {
			g.drawString("Antiban On", x, y+=15);
		} else {
			g.drawString("Antiban Off", x, y+=15);
		}
		
	}

	public void onFinish() {
		ScreenshotUtil.takeScreenshot(isLoggedIn());
		log(castCount + " Casts completed.");
		log(pointsGained + " Pizazz Points gained.");
	}
	
	/* Walks to the nearest tile in an array of tiles (path) */
	public void walkToNearest (RSTile[] array) {
		
		if(!isRunning()){
			setRun(true);
		}
		
		int nearest = 0;
		int distance = 1000;
		
		for (int counter = 0; counter < array.length; counter++) {
			if (distanceTo(array[counter]) < distance) {
				nearest = counter;
				distance = distanceTo(array[counter]);
			}
		}
		
		while(distanceTo(array[nearest]) > 5) {
			walkTileMM(randomizeTile(array[nearest], 2, 2));
			wait (distance * 200 + random (-100, 100));
		}
		
		return;
	}
	
	public void toPortal() {
		
		setCameraAltitude(true);
		
		RSTile halfTile = new RSTile (3363, 3314);
		RSTile portalTile = new RSTile(3361, 3318);
		
		if(!isRunning()){
			setRun(true);
		}
		
		while (distanceTo(halfTile) > 5) {
			walkTileMM(halfTile);
			wait (distanceTo(halfTile) * 200 + random (-100, 100));
		}
		
		while(distanceTo(portalTile) > 5) {
			walkTileMM(portalTile);
			wait (distanceTo(portalTile) * 200 + random (-100, 100));
		}
		
		state = "enter";
		
		return;
	}
	
	public boolean checkLocation () {
		
		if (getMyPlayer().getLocation().equals(new RSTile(3363, 9649)) ||
				getMyPlayer().getLocation().equals(new RSTile(3373, 9640)) ||
				getMyPlayer().getLocation().equals(new RSTile(3363, 9630)) ||
				getMyPlayer().getLocation().equals(new RSTile(3354, 9640))) {
				
				if (mode.equals("XP")) { 
					state = "run";
					return true;
				} else {
					state = "stones";
					return true;
				}
		}
		return false;
	}
	
	public void inPortal() {
		
		final RSObject portal = findObject(10779);
		while(!checkLocation()) {
			
			setCameraRotation(getAngleToObject(portal) + random(-15, 15));
			atObject(portal, "Enter");
			wait (random (2000, 3000));
			
		}
		return;
	}
	
	public RSItemTile getNearestTile (RSItemTile[] array) {

		int nearest = 0;
		int distance = 1000;
		
		for (int counter = 0; counter < array.length; counter++) {
			if (distanceTo(array[counter]) < distance) {
				nearest = counter;
				distance = distanceTo(array[counter]);
			}
		}
		
		return array[nearest];
	}
	
	public RSItemTile[] getItemTiles(RSTile[] array) {
		
		RSItemTile[] ItemTiles = new RSItemTile[6];
		int arrayLength = 0;
		
		for (int counter = 0; counter < array.length; counter++) {
			RSItemTile[] RawItemTiles = getGroundItemsAt(array[counter]);
			
			for(int counter2 = 0; counter2 < RawItemTiles.length; counter2++) {
				int itemID = RawItemTiles[counter2].getItem().getID();
				if(itemID == dstoneID) {
					ItemTiles[arrayLength] = (RawItemTiles[counter2]);
					arrayLength++;
				}
			}
		}
		
		RSItemTile[] finalItemTiles = new RSItemTile[arrayLength];
		System.arraycopy(ItemTiles, 0, finalItemTiles, 0, arrayLength);
		
		return finalItemTiles;
	}
	
	public void getDstone() {
		
		setRun(true);
		
		RSItemTile dstoneTile;
		
		while(getGroundItemByID(dstoneID) != null) {
			
			dstoneTile = getNearestTile(getItemTiles(dstoneSpawns));
			
			turnToTile(dstoneTile, 15);
			
			int distance = distanceTo(dstoneTile);
			RSTile myLocation = getMyPlayer().getLocation();
			
			if (distance > 15) {
				RSTile midway = new RSTile(
						(dstoneTile.getX() + myLocation.getX()) / 2,
						(dstoneTile.getY() + myLocation.getY()) / 2
				);
				
				while(distanceTo(midway) > 5) {
					walkTileMM(randomizeTile(midway, 2, 2));
					wait(distanceTo(midway) * 200 + random (-100, 100));
				}
				
				while(distanceTo(dstoneTile) > 5) {
					walkTileMM(randomizeTile(dstoneTile, 2, 2));
					wait(distanceTo(midway) * 200 + random (-100, 100));
				}
				
			} else if (distance >= 5) {
				
				while(distanceTo(dstoneTile) > 4) {
					walkTileMM(randomizeTile(dstoneTile, 2, 2));
					wait(distance * 200 + random (-100, 100));
				}
			}
			
			int oldCount = getInventoryCount(dstoneID);
			
			wait(random(200, 500));

			while (getInventoryCount(dstoneID) == oldCount && dstoneTile.getItem() != null) {
				
				atTile(dstoneTile, "Take");
				wait(random(800, 1200));
				
			}
			
		}
		
		if (getInventoryCount(dstoneID) != 0) {
			state = "cast";
		} else {
			state = "hop";
		}
		return;
	}
	
	public void toShapes() {
		
		walkToNearest(point2);
		walkToNearest(point1);
		
		RSObject shape = getNearestObjectByID (shapeIDs);
		RSTile shapeLocation = shape.getLocation();
		
		if (distanceTo(shapeLocation) == 5) {
			turnToObject(shape);
			wait (random(500, 1000));
		}
		
		while (distanceTo(shapeLocation) > random(4, 5)) {
			walkTileMM(shapeLocation);
			wait (distanceTo(shapeLocation) * 100 + random (-200, 200));
		}
		
		state = "pickup";
		
		return;
	}
	
	public void takeShapes() {
		RSObject shape = getNearestObjectByID (shapeIDs);
		
		while(!isInventoryFull()) {
		atObject (shape, "Take-from");
		wait(random(500, 750));
		}
		
		state = "cast";
		return;
	}
	
	public void cast() {
		
		RSItem shapes = getInventoryItemByID(shapeItemIDs);
		if (shapes == null) {
			
			if (mode.equals("XP")) {
				state = "deposit";
			} else {
				state = "hop";
			}
			
		} else {
		
			openTab(Constants.TAB_MAGIC);
			wait (random (100, 150));
			
			if (castType.equals("Dragonstone")) {
				
				int dstoneX = RSInterface.getInterface(192).getChild(52).getAbsoluteX();
				int dstoneY = RSInterface.getInterface(192).getChild(52).getAbsoluteY();
				moveMouse (dstoneX + random (0, 23), dstoneY + random (0, 23));
				
			} else if (castType.equals("Onyx")) {
				
				int onyxX = RSInterface.getInterface(192).getChild(62).getAbsoluteX();
				int onyxY = RSInterface.getInterface(192).getChild(62).getAbsoluteY();
				moveMouse (onyxX + random (0, 23), onyxY + random (0, 23));
				
			} else if (castType.equals("Diamond")) {
				
				int diamondX = RSInterface.getInterface(192).getChild(37).getAbsoluteX();
				int diamondY = RSInterface.getInterface(192).getChild(37).getAbsoluteY();
				moveMouse (diamondX + random (0, 23), diamondY + random (0, 23));
				
			}
		
		clickMouse (true);
		
			if (getInventoryCount(dstoneID) != 0) {
				
				RSItem castItem = getInventoryItemByID(shapeItemIDs);
				atInventoryItem(castItem.getID(), "Cast");
				
				wait(random(750, 1000));
				
			} else {
		
				moveMouse(704 + random (-5, 5), 446 + random (-5, 5));
				wait(random(50, 75));
				clickMouse (true);
				wait(random(750, 1000));
				
			}
			
			if (getCurrentTab() == Constants.TAB_INVENTORY) {
				clickMouse (true);
				wait(random(750, 1000));
			}
		
		}
		
		return;
	}
	
	public void deposit() {
		
		walkToNearest (point1);
		walkToNearest (point2);
		walkToNearest (point3);
		
		while (getInventoryCount(6902) != 0) {
		RSObject well = findObject(10803);
		atObject(well, "Deposit");
		wait (random(500, 750));
		}
		
		if (mode.equals("XP")) {
			state = "run";
		} else {
			state = "stones";
		}
		
		return;
	}
	
	public void antiban() {
		
		final char[] rotateLR = new char[] { KeyEvent.VK_LEFT,
				KeyEvent.VK_RIGHT };
		
		int selector = random (1, 5);

		int rand = random (0, 2);
		int period = random (200, 600);
		
		switch (selector) {
		
		case 1:
			
			if (debug)
			log("Antiban: Moving camera...");			
			
			Thread changeAltitude = new Thread (new Runnable() {
				public void run() {
					int altitude = random (30, 99);
					setCameraAltitude(altitude);
				}
			}
			);
			
			Bot.getInputManager().pressKey(rotateLR[rand]);
			try {
				
				changeAltitude.run();
				Thread.sleep(period);
				
			} catch (final Exception e) {
				log("Failed.");
			}
			Bot.getInputManager().releaseKey(rotateLR[rand]);
			
			wait (random(100, 250));
			
		case 2:
			
			if (debug)
			log("Antiban: Opening random tab...");
			openTab(random(0, 7));
			wait (random(400, 1200));
			
		case 3:
			
			if (debug)
			log("Antiban: Checking XP til next level...");
			openTab(Constants.TAB_STATS);
			wait(random(1, 20));
			moveMouse(567 + random(0, 25), 393 + random(0, 14));
			wait (random(800, 1600));
			
		case 4:
			
			if (debug)
			log("Antiban: Moving mouse...");
			moveMouse(random(1, 760), random(1, 499));
			
		}
		
		int interval = random(15000, 60000);
		antiTime = System.currentTimeMillis() + interval;
		
		if (debug)
		log ("Engaging antiban in " + interval / 1000 + " seconds...");

		return;
		
	}
	
	public boolean worldhop() {
		if (debug)
		log("Worldhopping, this may take 1-2 Minutes.");
		logout();
		if (RSInterface.getInterface(744).getChild(580).isValid()) {
			int x9 = random(345, 415);
			int y9 = random(242, 250);
			moveMouse(x9, y9);
			int positionX = (input.getX());
			int positionY = (input.getY());
			boolean succsess = false;
			wait(random(400, 800));
			if (positionX == x9 && positionY == y9) {
				succsess = true;
			}
			if (!succsess) {
				worldhop();
			}
			clickMouse(true);
			wait(random(4000, 6000));

			int x10 = random(84, 296);
			int y10 = random(148, 450);
			moveMouse(x10, y10);
			clickMouse(true);
			wait(random(4000, 6000));
			boolean loggedin = true;
			if (RSInterface.getInterface(744).getChild(639).isValid()) {
				
				String text1 = RSInterface.getInterface(744).getChild(639).getText();
				if (text1.equals("World 2")
				|| text1.equals("World 6")
				|| text1.equals("World 31")
				|| text1.equals("World 144")
				|| text1.equals("World 44")) {
					log("This is a Heavily Populated World, Choosing another one");
					loggedin = false;

				} else if (text1.contains("World 137")
						|| text1.contains("World 65")
						|| text1.contains("World 26")
						|| text1.contains("World 124")
						|| text1.contains("World 18")
						|| text1.contains("World 86")
						|| text1.contains("World 72")) {
					
					log("This is a PvP World, Choosing another one");
					loggedin = false;
				}
				
				if (loggedin) {
					login();
				} else {
					worldhop();
				}

			}
		}
		return isLoggedIn();

	}
	
	public int loop() {
		if (!isLoggedIn() || isWelcomeButton() || !StartedY) {
			StartedY = true;
			wait(1000);
			return random(250, 500);
		}
		
		if (getInventoryCount(564) == 0) {
			log ("Out of Cosmic runes");
			stopAllScripts();
		}
		
		if (getMyPlayer().getLocation().equals(new RSTile (3363, 3302))) {
			state = "portal";
		} else if (state == null && mode.equals("XP")) {
			state = "run";
		} else if (state == null && mode.equals("Pizazz Points")) {
			state = "stones";
		}
		
		if (state.equals("portal")) {
			status = "Running to portal";
			toPortal();
		}
		
		if (state.equals("enter")) {
			status = "Entering portal";
			inPortal();
		}
		
		if (mode.equals("XP")) {
		
			if (state.equals("run")) {
				status = "Running to shapes";
				toShapes();
			}
		
			if (state.equals("pickup")) {
				status = "Picking up shapes";
				takeShapes();
			}
		
			if (state.equals("cast")) {
				status = "Casting enchantment spell";
				cast();
			}
		
			if (state.equals("deposit")) {
				status = "Depositing orbs";
				deposit();
			}
		} else {
			
			if (state.equals("stones")) {
				status = "Gathering Dragonstones";
				getDstone();
			}
			
			if (state.equals("cast")) {
				status = "Casting enchantment spell";
				cast();
			}
			
			if (state.equals("hop")) {
				status = "World hopping";
				worldhop();
			}
			
		}
		
		if (System.currentTimeMillis() > antiTime && antiban && state != "hop") {
			status = "Engaging Antiban";
			antiban();
		}
		
		return random(100, 150);
	}

}